Skip to content

Update v0.8 spec with updated catalog negotiation style#136

Merged
jacobsimionato merged 15 commits intogoogle:mainfrom
jacobsimionato:custom-catalog
Dec 8, 2025
Merged

Update v0.8 spec with updated catalog negotiation style#136
jacobsimionato merged 15 commits intogoogle:mainfrom
jacobsimionato:custom-catalog

Conversation

@jacobsimionato
Copy link
Collaborator

Summary of changes:

  • Replace clientUiCapabilities message type with a similar metadata parameter which is included in every message, rather than just once.
  • Resolve ambiguities in the schema, e.g. whether custom components are additive or not.
  • Add JSON schemas for key metadata fields etc.
  • Rename "dynamic catalogs" to "inline catalogs".

Fixes #135

@jacobsimionato jacobsimionato requested a review from wrenj November 24, 2025 03:55
@jacobsimionato
Copy link
Collaborator Author

Hey, I overhauled this based on your new proposal. PTAL!


params.acceptsDynamicSchemas: (OPTIONAL) A boolean indicating if the agent can accept a clientUiCapabilities message containing a dynamicCatalog. If omitted, this defaults to false.
#### Parameter Definitions
- `params.acceptsInlineCatalogs`: (OPTIONAL) A boolean indicating if the agent can accept an `inlineCatalogs` array in the client's `a2uiClientCapabilities`. If omitted, this defaults to `false`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

single inline catalog right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see multiple below

whats the usecase you are envisioning here? not saying having an array is a problem just curious if it solves any problems not solved by a single inline catalog?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can totally see an ecosystem of inline catalogs evolving, available to client developers to include in their clients. You could concatenate them, I suppose, but why not have a list?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the agent picks a single catalog to use, the inline catalogs aren't concatenated, so the client would say here are 3 inline catalogs pick one which I don't understand

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My take 1. InlineCatalogs hopefully are only used in non-prod environments. The server agent permitting which catalog(s) in its agent card is the primary mechanism we should push for.
2. For inline catalogs, one can imagine client developers keeping separate catalog files for each of their components. If we support that, then both the server and client need to have a long list of catalogs to manage. The client could collate components off of each catalog and send the list inline.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put multiple inline catalogs here because I figured it's consistent with advertising multiple well-known catalogs which an agent can pick from. If a client supports 5 different catalogs, shouldn't it also be able to advertise them all inline? Or should it have to pick only one of them to advertise inline, and advertise the rest only via ID?

Thinking about it a bit more, I can see how this is not especially likely to be used in practice, because how will agents know which catalog to pick? But I kind of still want to leave it here, because it doesn't add much complexity to the API, and I think it might even make the client SDKs simpler - you will just have a boolean like "advertiseCatalogsInline" rather than a setting which specific catalog of your many catalogs you'd like to advertise inline.

I agree with Mandar that this is mostly a mechanism for local development, so we don't have to think too hard about it.

How strongly does everyone feel? I'll remove this if there is consensus that it's overly complex!

Copy link
Collaborator

@gspencergoog gspencergoog Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it as a list. dictionary.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

multiple inline catalogs sgtm

its not a list though its a dictionary right? of catalogId: inlineCatalogJson ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right, it's a dict.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The catalog_description_schema contains catalogId already, which I think makes sense - a catalog should declare it's Id. Now, inlineCatalogs references this schema. So I think it makes sense to just have an array of these, and each of them has an ID in it, rather than redundantly including the ID as a key as well. Yes, there could be duplicate Ids, and that would be an error.

WDYT?

- `surfaceUpdate`: Provides a list of component definitions to be added to or updated in a specific UI area called a "surface."
- `dataModelUpdate`: Provides new data to be inserted into or to replace a surface's data model. Each surface has its own data model.
- `beginRendering`: Signals to the client that it has enough information to perform the initial render, specifying the ID of the root component.
- `beginRendering`: Signals to the client that it has enough information to perform the initial render, specifying the ID of the root component and, optionally, the component catalog to use.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd require it in begin render, or you could default it to the standard one

Copy link
Collaborator

@dmandar dmandar Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the agent card option not sufficient here?

Copy link
Collaborator Author

@jacobsimionato jacobsimionato Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wrenj Re requiring this: I want to add it as an optional parameter to beginRender in v0.8 and default to standard catalog, to make this change non-breaking. Otherwise all our agents theoretically need updating right away. In v0.9, let's make this required and explicit. I filed #193 for this.

@dmandar Re the switch I've made here to having the client advertise multiple catalogs and have the server choose, instead of the inverse - see https://docs.google.com/document/d/1SppqNwHytVIUp7o8x5py5Z7AIiMdz-pzgC0SWh9qfkE/edit?tab=t.lwpqe4lgroyz#bookmark=id.p3dk9n24f9ja which was prompted by James's request above. I think it's important that the agent choose the catalog, because in a multi-agent system, the client may not know which subagent is going to reply, so it can't know which catalog to choose.

"metadata": {
"a2uiClientCapabilities": {
"supportedCatalogIds": [
"a2ui.org:standard_catalog_0_8_0",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not opposed to using uris here, it could help debugging

I do like the flexible approach with ids though, eg google could embed the rev number google3/learning/agents/moma_catalog@12342322

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, URIs are good because they can be self documenting, even if only used as identifiers. (e.g. https://json-schema.org/draft/2020-12/schema )

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to URIs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept the name as 'supportedCatalogIds', but switched to suggesting URIs as a convention, and updated examples. Does that sound okay?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm


The server receives the client's capabilities and chooses a catalog to use for a specific UI surface. The server specifies its choice in the `beginRendering` message using the `catalogId` field.

- `catalogId` (string, optional): The identifier of the chosen catalog. This ID must be one of the `supportedCatalogIds` or the `catalogId` from one of the `inlineCatalogs` provided by the client.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we require this? in your example if its not present, what does the client do? just assume the default catalog?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to add it as an optional parameter to beginRender in v0.8 and default to standard catalog, to make this change non-breaking. Otherwise all our agents theoretically need updating right away. Filed #193 to make it required for v0.9.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh breaking changes are fine, nobody is really using in 1P, and updating the agent samples is easy, not sure about for other teams you work with

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey that's fair. I guess I want to avoid creating more work trying to get all the renderers in sync for v0.8 too!


- `catalogId` (string, optional): The identifier of the chosen catalog. This ID must be one of the `supportedCatalogIds` or the `catalogId` from one of the `inlineCatalogs` provided by the client.

If the `catalogId` is omitted, the client **MUST** default to the standard catalog for the protocol version (`a2ui.org:standard_catalog_0_8_0`).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this helpful versus requiring it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above - non breaking for now.

#### Schemas for Developers

When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., `server_to_client_with_standard_catalog.json`). This provides the LLM with a strict definition of all available components and their properties, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation.
When building an agent, it is recommended to use a resolved schema that includes the specific component catalog you are targeting (e.g., a custom schema combining `server_to_client.json` with your `my-company.com:custom-reporting-catalog-1.2` definition). This provides the LLM with a strict definition of all available components and their properties, leading to more reliable UI generation. The generic `server_to_client.json` is the abstract wire protocol, while the resolved schema is the concrete tool for generation.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add some description of how to build the final catalog

heres the logic i used
https://github.com/google/A2UI/blob/main/a2a_agents/python/adk/samples/rizzcharts/component_catalog_builder.py#L80

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some example logic.


params.acceptsDynamicSchemas: (OPTIONAL) A boolean indicating if the agent can accept a clientUiCapabilities message containing a dynamicCatalog. If omitted, this defaults to false.
#### Parameter Definitions
- `params.acceptsInlineCatalogs`: (OPTIONAL) A boolean indicating if the agent can accept an `inlineCatalogs` array in the client's `a2uiClientCapabilities`. If omitted, this defaults to `false`.
Copy link
Collaborator

@gspencergoog gspencergoog Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it as a list. dictionary.

Copy link
Collaborator

@dmandar dmandar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM..please follow up with Ava to get this implemented on lit.

@jacobsimionato jacobsimionato merged commit b67bdbf into google:main Dec 8, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Properly document the revised, metadata-based catalog negotiation mechanism in the v0.8 spec

4 participants